package util

import (
	"encoding/json"
	"fmt"
	"gitee.com/manoshi/go-util/exception"
	"math/rand"
	"sort"
	"strconv"
	"strings"
	"time"
)

// 生成: 时间戳 + 设置前缀 ＋ 随即字符串
const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"

func FandomString(strlen int) string {
	rand.Seed(time.Now().UnixNano())
	result := make([]byte, strlen)
	for i := 0; i < strlen; i++ {
		result[i] = alphanum[rand.Intn(len(alphanum))]
	}
	return string(result)
}

func IsEmpty(s *string) bool {
	return s == nil || *s == ""
}

func IsNil(i interface{}) bool {
	if i == nil {
		return true
	}
	return false
}

func AppendForSplitComma(list, item string) string {
	if IsEmpty(&list) {
		return item
	} else {
		return fmt.Sprintf("%s,%s", list, item)
	}
}

func ContainsForSplitComma(list, item string) bool {
	return containsForSplit(list, item, ",")
}

func containsForSplit(list, item, character string) bool {
	if !IsEmpty(&list) {
		if strings.Contains(list, character) {
			return strings.Index(list, item+character) == 0 ||
				strings.Contains(list, character+item+character) ||
				strings.Index(list, character+item) == len(list)-len(character+item)
		} else {
			return list == item
		}
	}
	return false
}

//HideString 脱敏字符串
/**
orgStr 原字符串
preFixLength 前面不脱敏字符长度
postFixLength 后面不脱敏字符长度
minLength 需要脱敏字符串最小长度，如果没满足按照字符串长度全脱敏
stringType 字符串类型 1：普通字符，2：带有中午特殊字符
*/
func HideString(orgStr *string, preFixLength, postFixLength, minLength int) string {
	str := ""
	if orgStr == nil {
		return str
	} else {
		str = *orgStr
	}
	strLength := len([]rune(str))
	if strLength >= minLength {
		first3Chars := string([]rune(str)[0:preFixLength])
		last2Chars := string([]rune(str)[strLength-postFixLength:])
		hiddenStr := strings.Repeat("*", strLength-preFixLength-postFixLength)
		return fmt.Sprintf("%s%s%s", first3Chars, hiddenStr, last2Chars)
	} else {
		return strings.Repeat("*", strLength)
	}
}

func DimName(name *string) string {
	if IsEmpty(name) {
		return ""
	}
	t := *name
	switch len([]rune(t)) {
	case 0:
	case 1:
		return "*"
	case 2:
		return HideString(name, 1, 0, 2)
	default:
		return HideString(name, 1, 1, 3)
	}
	return "*"
}

func DimPhone(phone *string) string {
	return HideString(phone, 3, 2, 11)

}

func DimBankCardNo(orgCardNo *string) string {
	return HideString(orgCardNo, 3, 2, 11)
}

/**
参数一：原图片路径
参数二：host
参数三：原图片分隔符
参数四：结果图片的分隔符，可不传默认为原图片分隔符
*/
func BuildPicFull(org ...string) string {
	rd := ""
	var orgPic, host, sep, rdSep string
	if len(org) == 3 || len(org) == 4 {
	} else {
		panic("构建图片全路径参数错误")
	}
	orgPic = org[0]
	if orgPic == "" {
		return rd
	}
	host = org[1]
	sep = org[2]
	if len(org) == 3 {
		rdSep = sep
	}
	if len(org) == 4 {
		rdSep = org[3]
	}
	pics := strings.Split(orgPic, sep)
	for _, pic := range pics {
		if strings.TrimSpace(pic) != "" {
			if strings.Index(pic, "http") == 0 {
				rd += fmt.Sprintf("%s%s", pic, rdSep)
			} else {
				rd += fmt.Sprintf("%s%s%s", host, pic, rdSep)
			}
		}
	}
	return rd[0 : len(rd)-1]
}

//GetDHMS 根据秒获取天数小时数分钟数秒数
func GetDHMS(second int32) (int32, int32, int32, int32) {
	min := second / 60
	return min / 60 / 24, min / 60 % 24, min % 60, second % 60
}

//FormatDHMS 将秒格式化为x天x时x分x秒
func FormatDHMS(second int32) string {
	d, h, m, s := GetDHMS(second)
	f := ""
	if d > 0 {
		f += fmt.Sprintf("%d天", d)
	}
	if h > 0 {
		f += fmt.Sprintf("%d小时", h)
	}
	if m > 0 {
		f += fmt.Sprintf("%d分钟", m)
	}
	if s > 0 {
		f += fmt.Sprintf("%d秒", s)
	}
	if f == "" {
		return "0秒"
	}
	return f
}

func getDHM(min int32) (int32, int32, int32) {
	return min / 60 / 24, min / 60 % 24, min % 60
}
func FormatDHM(min int32) string {
	d, h, m := getDHM(min)
	f := ""
	if d > 0 {
		f += fmt.Sprintf("%d天", d)
	}
	if h > 0 {
		f += fmt.Sprintf("%d小时", h)
	}
	if m > 0 {
		f += fmt.Sprintf("%d分钟", m)
	}
	return f
}

func SubstringChinese(s string, start, end int) string {
	sArray := []rune(s)
	if end > len(sArray) {
		end = len(sArray)
	}
	if start < 0 {
		start = 0
	}
	if start > end {
		return ""
	}
	str := string([]rune(s)[start:end])
	return str
}

func SplitInt32(siteTypesStr string) []int32 {
	var rd []int32
	siteTypes := strings.Split(siteTypesStr, ",")
	for _, siteType := range siteTypes {
		if siteType == "" {
			continue
		}
		i, err := strconv.Atoi(siteType)
		if err == nil {
			rd = append(rd, int32(i))
		} else {
			exception.ThrowsErr(err)
		}
	}
	return rd
}

func StructToSortedJSON(v interface{}) (string, error) {
	// 将结构体转换为 map[string]interface{}
	data, err := json.Marshal(v)
	if err != nil {
		return "", fmt.Errorf("failed to marshal struct: %v", err)
	}

	var rawMap map[string]interface{}
	if err := json.Unmarshal(data, &rawMap); err != nil {
		return "", fmt.Errorf("failed to unmarshal to map: %v", err)
	}

	// 获取所有键并排序
	keys := make([]string, 0, len(rawMap))
	for key := range rawMap {
		keys = append(keys, key)
	}
	sort.Strings(keys)

	// 创建一个新的有序 map
	sortedMap := make(map[string]interface{})
	for _, key := range keys {
		sortedMap[key] = rawMap[key]
	}

	// 将排序后的 map 转换为 JSON 字符串
	sortedJSON, err := json.Marshal(sortedMap)
	if err != nil {
		return "", fmt.Errorf("failed to marshal sorted map: %v", err)
	}

	return string(sortedJSON), nil
}
